2777. Count Color

 

Chosen Problem Solving and Program design as an optional course, you are required to solve all kinds of problems. Here, we get a new problem.

There is a very long board with length L centimeter, L is a positive integer, so we can evenly divide the board into L segments, and they are labeled by 1, 2, ... L from left to right, each is 1 centimeter long. Now we have to color the board - one segment with only one color. We can do following two operations on the board:

1. "C A B C" Color the board from segment A to segment B with color C.

2. "P A B" Output the number of different colors painted between segment A and segment B (including).

In our daily life, we have very few words to describe a color (red, green, blue, yellow…), so you may assume that the total number of different colors T is very small. To make it simple, we express the names of colors as color 1, color 2, ... color T. At the beginning, the board was painted in color 1. Now the rest of problem is left to your.

 

Input. First line of input contains L (1 ≤ L ≤ 100000), T (1 ≤ T ≤ 30) and O (1 ≤ O ≤ 100000). Here O denotes the number of operations. Following O lines, each contains "C A B C" or "P A B" (here A, B, C are integers, and A may be larger than B) as an operation defined previously.

 

Output. Ouput results of the output operation in order, each line contains a number.

 

Sample Input

2 2 4

C 1 1 2

P 1 2

C 2 2 2

P 1 2

 

Sample Output

2

1

 

 

РЕШЕНИЕ

дерево отрезков

 

Анализ алгоритма

Построим дерево отрезков, поддерживающее операцию or и присваивание на отрезке. Поскольку разных цветов имеется до 30, информацию о цветах на отрезке будем хранить в маске (достаточно не более 30 бит). Например, если фундаментальный отрезок [l; r] покрывается цветами номер 1, 3 и 5, то соответствующая вершина хранит OrVal = 21 = 101012.

Изначально все сегменты отрезка [1; L] покрашены цветом 1. Построим на нем дерево отрезков, положив во всех вершинах OrVal = 1.

Когда при обновлении фундаментальный отрезок [l; r] красится цветом c, то положим в нем OrVal = 2c = (1 << c). Если левый сын – отрезок [l; m] покрашен цветами из множества mask1, а правый сын – отрезок [m + 1; r] покрашен цветами из множества mask2, то отцовская вершина – отрезок [l; r] будет покрашена цветами из множества mask1 | mask2.

При запросе  P A B запускаем функцию Query(A, B), которая возвращает маску, содержащую подмножество цветов на отрезке [A; B]. Количество цветов равно числу единиц в бинарном представлении маски, что и вычисляем в функции bits.

 

Реализация алгоритма

 

#include <cstdio>

#include <algorithm>

#define MAX 100010

using namespace std;

 

struct node

{

  int OrVal, add;

} SegTree[4*MAX];

 

void build(int Vertex, int Left, int Right)

{

  if (Left == Right)

  {

    SegTree[Vertex].OrVal = 1; // color 1

    SegTree[Vertex].add = -1;

  }

  else

  {

    int Middle = (Left + Right) / 2;

    build (2*Vertex, Left, Middle);

    build (2*Vertex+1, Middle+1, Right);

    SegTree[Vertex].OrVal = SegTree[2*Vertex].OrVal | SegTree[2*Vertex+1].OrVal;

    SegTree[Vertex].add = -1;

  }

}

 

void Push(int Vertex, int LeftPos, int Middle, int RightPos)

{

  if (SegTree[Vertex].add != -1)

  {

    SegTree[2*Vertex].add = SegTree[2*Vertex+1].add = SegTree[Vertex].add;

    SegTree[2*Vertex].OrVal = SegTree[2*Vertex+1].OrVal = SegTree[Vertex].OrVal;

    SegTree[Vertex].add = -1;

  }

}

 

void SetValue(int Vertex, int LeftPos, int RightPos, int Left, int Right, int Value)

{

  if (Left > Right) return;

  if ((LeftPos == Left) && (RightPos == Right))

  {

    SegTree[Vertex].add = 1;

    SegTree[Vertex].OrVal = 1 << (Value - 1);

    return;

  }

 

  int Middle = (LeftPos + RightPos) / 2;

  Push(Vertex,LeftPos,Middle,RightPos);

 

  SetValue(2*Vertex, LeftPos, Middle, Left, min(Middle,Right), Value);

  SetValue(2*Vertex+1, Middle+1, RightPos, max(Left,Middle+1), Right, Value);

 

  SegTree[Vertex].OrVal = SegTree[2*Vertex].OrVal | SegTree[2*Vertex+1].OrVal;

}

 

long long Query(int Vertex, int LeftPos, int RightPos, int Left, int Right)

{

  if (Left > Right) return 0;

  if ((LeftPos == Left) && (RightPos == Right)) return SegTree[Vertex].OrVal;

 

  int Middle = (LeftPos + RightPos) / 2;

  Push(Vertex,LeftPos,Middle,RightPos);

 

  return Query(2*Vertex, LeftPos, Middle, Left, min(Middle,Right)) |

         Query(2*Vertex+1, Middle+1, RightPos, max(Left,Middle+1), Right);

}

 

int bits(int n)

{

  if (n < 2) return n;

  return bits(n / 2) + n % 2;

}

 

int L, t, o, n, l, r, x;

char c;

 

int main(void)

{

  scanf("%d %d %d\n",&L,&t,&o);

  build(1,1,L);

  while(o--)

  {

    scanf("%c ",&c);

    if (c == 'C')

    {

      scanf("%d %d %d\n",&l,&r,&x);

      if (l > r) swap(l,r);

      SetValue(1,1,L,l,r,x);

    }

    else

    {

      scanf("%d %d\n",&l,&r);

      if (l > r) swap(l,r);

      printf("%lld\n",bits(Query(1,1,L,l,r)));

    }

  }

  return 0;

}